package com.qfmy.common.utils;


import com.qfmy.common.exception.BaseException;
import com.qfmy.common.result.ResultCodeEnum;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;
/**
 * @author 清风明月
 * @Package com.qfmy.common.utils
 * @date 2025/11/11
 * @descriptio jwt工具类
 */
@SuppressWarnings("all")
public class JwtUtil {

    /**
     * JWT签名密钥
     * 使用HS256算法所需的HMAC SHA密钥，通过指定字符串生成
     */
    private static SecretKey secretKey = Keys.hmacShaKeyFor("CY29Eb04RPNyQPxACH2jBNWFGn0ypMhc".getBytes());

    /**
     * 定义密钥过期时间 七天
     */
    private static final long EXPIRE_TIME = 7 * 24 * 60 * 60 * 1000;

    /**
     * 创建JWT令牌
     * @param userId 用户ID，作为令牌中的自定义信息
     * @param username 用户名，作为令牌中的自定义信息
     * @return 生成的JWT令牌字符串
     */
    public static String createToken(Long userId, String phone) {

        return Jwts.builder()
                .setSubject("LOGIN_USER") // 设置JWT主题，标识令牌用途（此处为登录用户）
                // 设置过期时间：当前时间 + 1天（单位：毫秒）
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
                .claim("userId", userId) // 添加自定义声明：用户ID
                .claim("phone", phone) // 添加自定义声明：手机号
                .signWith(secretKey, SignatureAlgorithm.HS256) // 使用指定密钥和HS256算法签名
                .compact(); // 压缩生成最终的JWT字符串
    }

    /**
     * 解析JWT令牌，获取其中的声明信息
     * @param token 待解析的JWT令牌字符串
     * @return 令牌中包含的声明（Claims）对象，可从中获取主题、过期时间及自定义信息
     * @throws BaseException 当令牌为null、过期或无效时抛出，包含具体错误码
     */
    public static Claims parseToken(String token) {

        // 令牌为null时，抛出未登录异常
        if (token == null) {
            throw new BaseException(ResultCodeEnum.APP_LOGIN_AUTH);
        }

        try {
            // 解析令牌并验证签名
            Jws<Claims> claimsJws = Jwts.parserBuilder()
                    .setSigningKey(secretKey) // 设置用于验证签名的密钥
                    .build()
                    .parseClaimsJws(token); // 解析令牌
            return claimsJws.getBody(); // 返回令牌中的声明体
        } catch (ExpiredJwtException e) {
            // 令牌过期时抛出的异常
            throw new BaseException(ResultCodeEnum.TOKEN_EXPIRED);
        } catch (JwtException e) {
            // 其他JWT相关异常（如签名无效、格式错误等），统一视为令牌无效
            throw new BaseException(ResultCodeEnum.TOKEN_INVALID);
        }
    }

}